home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr47 / wasm223.zip / SLEEPERE.ASM < prev    next >
Assembly Source File  |  1993-05-04  |  32KB  |  1,125 lines

  1. ; SLEEPER, EGA Version
  2. ; by Eric Tauck
  3. ;
  4. ; This program is a TSR that automatically blanks
  5. ; an EGA or VGA screen after a specified amount of
  6. ; time to prevent screen burn-in.
  7. ;
  8. ; The screen is blanked by setting the first 16
  9. ; palette registers to black.  The screen is
  10. ; unblanked by restoring the palette registers.
  11. ; Will not work in VGA 256 color mode or CGA
  12. ; graphics modes.  It should work in all other
  13. ; standard graphic and text modes.
  14. ;
  15. ; NOTES: SLEEPER will not work right if the video
  16. ; mode is switched without the palette registers
  17. ; being restored to their default state (by the
  18. ; application or the ROM).  This problem, if it
  19. ; ever occurs, will probably only happen when the
  20. ; adapter is switched from one graphics mode to
  21. ; another.  SLEEPER will also not work right with
  22. ; programs that set the palette directly through
  23. ; the video controller registers, rather than
  24. ; using the ROM routines.
  25.  
  26.         UNUSED+
  27.         JUMP+
  28.  
  29.         jmp     start           ;jump to entry point
  30.  
  31. ;****************************************
  32. ; Resident Data
  33.  
  34. VER_HI  EQU     1               ;high version number
  35. VER_LO  EQU     30              ;low version number
  36.  
  37. SIGN1   EQU     0534CH          ;first part of signature
  38. SIGN2   EQU     04550H          ;second part of signature
  39.  
  40. BIOSEG  EQU     0040H           ;BIOS data area segment
  41. BIOSHF  EQU     0017H           ;BIOS shift bits
  42. SMASK   EQU     00001111B       ;hot key shift mask
  43. SHIFT   EQU     00001100B       ;hot key shift bits (CONTROL + ALTERNATE)
  44.  
  45. func    DB      ?               ;keyboard function number
  46.  
  47. ;--- original interrupt handlers
  48.  
  49. int_09  LABEL   DWORD   ;old interrupt 9
  50.         DW      ?
  51.         DW      ?
  52.  
  53. int_10  LABEL   DWORD   ;old interrupt 10
  54.         DW      ?
  55.         DW      ?
  56.  
  57. int_16  LABEL   DWORD   ;old interrupt 16
  58.         DW      ?
  59.         DW      ?
  60.  
  61. int_1C  LABEL   DWORD   ;old interrupt 1C
  62.         DW      ?
  63.         DW      ?
  64.  
  65. int_21  LABEL   DWORD   ;old interrupt 21
  66.         DW      ?
  67.         DW      ?
  68.  
  69. ;--- flags
  70.  
  71. FIXED   EQU     0001H   ;video state fixed
  72. DISPL   EQU     0002H   ;video displayed
  73. FORCE   EQU     0004H   ;forced timeout
  74. flags   DW      0000H   ;current flag settings
  75.  
  76. ;--- timer data
  77.  
  78. ticks   DW      5460    ;count value (5 min * 60 sec/min * 18.2 tic/sec)
  79. timer   DW      ?       ;timer value
  80.  
  81. ;--- resident functions
  82.  
  83. NOTHING EQU     0       ;do nothing
  84. RESET   EQU     1       ;reset timer
  85. SHOW    EQU     2       ;screen on
  86. HIDE    EQU     3       ;screen off
  87. TIME    EQU     4       ;force timeout
  88.  
  89. functab LABEL   WORD                    ;resident function table
  90.         DW      OFFSET dummy
  91.         DW      OFFSET screen_reset
  92.         DW      OFFSET screen_on
  93.         DW      OFFSET screen_off
  94.         DW      OFFSET timeout
  95.  
  96. ;--- palette register values
  97.  
  98. pal_off DB      000H, 000H, 000H, 000H, 000H, 000H, 000H, 000H
  99.         DB      000H, 000H, 000H, 000H, 000H, 000H, 000H, 000H 
  100.         DB      000H
  101.  
  102. pal_on  DB      000H, 001H, 002H, 003H, 004H, 005H, 014H, 007H
  103.         DB      038H, 039H, 03AH, 03BH, 03CH, 03DH, 03EH, 03FH 
  104.         DB      000H
  105.  
  106. pal_def DB      000H, 001H, 002H, 003H, 004H, 005H, 014H, 007H
  107.         DB      038H, 039H, 03AH, 03BH, 03CH, 03DH, 03EH, 03FH 
  108.         DB      000H
  109.  
  110. ;****************************************
  111. ; Resident Code
  112.  
  113. ;========================================
  114. ; Low level control.
  115.  
  116. ;--- reset timer
  117.  
  118. reset_timer PROC    NEAR
  119.         seg     cs
  120.         push    ticks           ;ticks on stack
  121.         seg     cs
  122.         pop     timer           ;load timer
  123.         ret
  124.         ENDP
  125.  
  126. ;--- turn off video
  127.  
  128. video_off PROC    NEAR
  129.         push    ax
  130.         push    dx
  131.         push    es
  132.         mov     ax, 1002H               ;set all palette registers
  133.         mov     dx, OFFSET pal_off      ;offset of palette values
  134.         push    cs
  135.         pop     es                      ;segment of palette values
  136.         pushf
  137.         seg     cs
  138.         call    int_10                  ;execute int 10
  139.         seg     cs
  140.         and     flags, NOT DISPL        ;clear flag
  141.         pop     es
  142.         pop     dx
  143.         pop     ax
  144.         ret
  145.         ENDP
  146.  
  147. ;--- turn on video
  148.  
  149. video_on PROC    NEAR
  150.         push    ax
  151.         push    dx
  152.         push    es
  153.         mov     ax, 1002H               ;set all palette registers
  154.         mov     dx, OFFSET pal_on       ;offset of palette values
  155.         push    cs
  156.         pop     es                      ;segment of palette values
  157.         pushf
  158.         seg     cs
  159.         call    int_10                  ;execute int 10
  160.         seg     cs
  161.         or      flags, DISPL            ;set flag
  162.         pop     es
  163.         pop     dx
  164.         pop     ax
  165.         ret
  166.         ENDP
  167.  
  168. ;========================================
  169. ; Screen functions.
  170.  
  171. ;--- reset screen timer
  172.  
  173. screen_reset PROC NEAR
  174.         seg     cs
  175.         and     flags, NOT FIXED ;clear fixed flag
  176.         call    reset_timer     ;reset timer
  177.         seg     cs
  178.         test    flags, DISPL    ;check if screen on
  179.         jnz     novon
  180.         call    video_on        ;turn on screen
  181. novon   ret
  182.         ENDP
  183.  
  184. ;--- force timeout
  185.  
  186. timeout PROC NEAR
  187.         seg     cs
  188.         and     flags, NOT FIXED ;clear fixed flag (reset)
  189.         seg     cs
  190.         or      flags, FORCE    ;set forced timeout flag
  191.         seg     cs
  192.         mov     timer, 18       ;set timer to two seconds
  193.         ret
  194.         ENDP
  195.  
  196. ;--- turn screen off
  197.  
  198. screen_off PROC NEAR
  199.         seg     cs
  200.         or      flags, FIXED    ;set fixed flag
  201.         seg     cs
  202.         mov     timer, 0        ;zero timer
  203.         call    video_off       ;turn off screen
  204.         ret
  205.         ENDP
  206.  
  207. ;--- screen on
  208.  
  209. screen_on PROC NEAR
  210.         seg     cs
  211.         or      flags, FIXED    ;set fixed flag
  212.         seg     cs
  213.         mov     timer, 0        ;zero timer
  214.         call    video_on        ;turn on screen
  215.         ret
  216.         ENDP
  217.  
  218. ;--- dummy function
  219.  
  220. dummy   PROC    NEAR
  221.         ret
  222.         ENDP
  223.  
  224. ;--- transfer to screen routine in BX
  225.  
  226. screen_func PROC NEAR
  227.         shl     bx                      ;convert number to offset
  228.         seg     cs
  229.         jmp     WORD [functab + bx]     ;branch to routine
  230.         ENDP
  231.  
  232. ;========================================
  233. ; Interrupt 09H handler.
  234.  
  235. key_han PROC    NEAR
  236.         seg     cs
  237.         test    flags, FIXED OR FORCE   ;check if fixed state or forced timeout
  238.         jnz     kdone
  239.         call    screen_reset    ;reset timer and screen
  240. kdone   seg     cs
  241.         jmp     int_09          ;branch to old keyboard handler
  242.         ENDP
  243.  
  244. ;========================================
  245. ; Copy a set of palette register values
  246. ; to the screen on palette values.
  247. ;
  248. ; In: DX:AX= address of palette register
  249. ;     values.
  250.  
  251. pal_load PROC   NEAR
  252.         pushf                   ;save flags (because direction is modified)
  253.         push    cx
  254.         push    di
  255.         push    si
  256.         push    ds
  257.         push    es
  258.         mov     si, ax                  ;
  259.         mov     ds, dx                  ;-- source address
  260.         mov     di, OFFSET pal_on       ;
  261.         push    cs                      ;-- destination address
  262.         pop     es                      ;
  263.         mov     cx, 17                  ;17 bytes
  264.         cld
  265.         rep
  266.         movsb                           ;copy
  267.         pop     es
  268.         pop     ds
  269.         pop     si
  270.         pop     di
  271.         pop     cx
  272.         popf
  273.         ret
  274.         ENDP
  275.  
  276. ;========================================
  277. ; Interrupt 10H handler.
  278.  
  279. vid_han PROC    NEAR
  280.  
  281. ;=== check if change mode
  282.  
  283.         cmp     ah, 0                   ;check if change mode
  284.         jne     vidhan1                 ;jump if not
  285.  
  286.         push    ax
  287.         push    dx
  288.         mov     ax, OFFSET pal_def      ;-- address of default palette
  289.         mov     dx, cs                  ;
  290.         call    pal_load                ;load palette
  291.         pop     dx
  292.         pop     ax
  293.         jmps    vdone
  294.  
  295. ;=== check if set palette registers
  296.  
  297. vidhan1 cmp     ah, 10H                 ;check if set palette
  298.         jne     vdone                   ;exit if not
  299.  
  300. ;--- set individual palette register
  301.  
  302.         cmp     al, 0                   ;check if set single register
  303.         jne     vidhan2
  304.  
  305.         mov     ax, bx                  ;save BX in AX
  306.         sub     bh, bh                  ;palette index in BX
  307.         seg     cs
  308.         mov     [pal_on+bx], ah         ;save color value
  309.         mov     bx, ax                  ;restore BX
  310.         mov     ax, 1000H               ;reload AX
  311.         jmps    vdone
  312.  
  313. ;--- set overscan register
  314.  
  315. vidhan2 cmp     al, 1
  316.         jne     vidhan3
  317.  
  318.         seg     cs
  319.         mov     [pal_on+16], bh         ;save over scan value
  320.         jmps    vdone
  321.  
  322. ;--- set all palette registers
  323.  
  324. vidhan3 cmp     al, 2
  325.         jne     vdone
  326.  
  327.         push    dx
  328.         mov     ax, dx
  329.         mov     dx, es
  330.         call    pal_load        ;load palette
  331.         mov     ax, 1002H       ;restore AX
  332.         pop     dx              ;restore DX
  333.  
  334. ;--- finished
  335.  
  336. vdone   seg     cs
  337.         jmp     int_10          ;branch to old handler
  338.         ret
  339.         ENDP
  340.  
  341. ;========================================
  342. ; Check for a hotkey and pass command
  343. ; to resident sleeper.  NOTE: all the
  344. ; flags except CY are preserved.
  345. ;
  346. ; In: AH= scan code.
  347. ;
  348. ; Out: CY= set if hotkey pressed,
  349. ;      cleared if not.
  350.  
  351. key_check PROC  NEAR
  352.         pushf
  353.         push    ax
  354.         push    bx
  355.  
  356. ;--- check scan code
  357.  
  358.         mov     bx, RESET
  359.         cmp     ah, 19          ;R - reset timer
  360.         je      kshft
  361.         mov     bx, SHOW
  362.         cmp     ah, 47          ;V - visible screen
  363.         je      kshft
  364.         mov     bx, HIDE 
  365.         cmp     ah, 35          ;H - hidden screen
  366.         je      kshft
  367.         mov     bx, TIME
  368.         cmp     ah, 20          ;T - force timeout
  369.         je      kshft
  370.  
  371. kcdone  pop     bx
  372.         pop     ax
  373.         popf
  374.         clc
  375.         ret
  376.  
  377. ;--- check shift state
  378.  
  379. kshft   push    ds
  380.         mov     ax, BIOSEG      ;data area segment
  381.         mov     ds, ax
  382.         mov     al, [BIOSHF]    ;load first shift byte
  383.         pop     ds
  384.  
  385.         and     al, SMASK       ;mask bits
  386.         cmp     al, SHIFT       ;check if proper shift
  387.         jne     kcdone          ;exit if not
  388.  
  389. ;--- execute resident function
  390.  
  391.         call    screen_func     ;execute screen function
  392.  
  393.         pop     bx
  394.         pop     ax
  395.         popf
  396.         stc
  397.         ret
  398.         ENDP
  399.  
  400. ;========================================
  401. ; Interrupt 16H handler.
  402.  
  403. key2_han PROC   NEAR
  404.         seg     cs
  405.         mov     func, ah        ;save function number
  406.  
  407.         cmp     ah, 0           ;check if fetch key
  408.         je      k2fet
  409.         cmp     ah, 10H         ;check if fetch extended key
  410.         je      k2fet
  411.         cmp     ah, 1           ;check if keyboard status
  412.         je      k2stat
  413.         cmp     ah, 11H         ;check if extended keyboard status
  414.         je      k2stat
  415.         seg     cs
  416.         jmp     int_16          ;branch to original keyboard handler
  417.  
  418. ;--- fetch keystroke
  419.  
  420. k2fet1  seg     cs
  421.         mov     ah, func        ;load function
  422.  
  423. k2fet   pushf
  424.         seg     cs
  425.         call    int_16          ;call keyboard handler
  426.         call    key_check       ;check for hotkey
  427.         jc      k2fet1          ;loop back if so
  428.  
  429.         iret
  430.  
  431. ;--- keyboard status
  432.  
  433. k2stat1 sub     ah, ah          ;fetch key function
  434.         pushf
  435.         seg     cs
  436.         call    int_16          ;call keyboard handler
  437.         seg     cs
  438.         mov     ah, func        ;reload function
  439.         
  440. k2stat  pushf
  441.         seg     cs
  442.         call    int_16          ;call keyboard handler
  443.         jz      k2e2            ;exit if no key
  444.  
  445.         call    key_check       ;check for hotkey
  446.         jc      k2stat1         ;loop back if so
  447.  
  448. k2e2    retf    2               ;return with flags
  449.         ENDP
  450.  
  451. ;========================================
  452. ; Interrupt 1CH handler.
  453.  
  454. tic_han PROC    NEAR
  455.         seg     cs
  456.         cmp     timer, 0                ;check if timer zero
  457.         je      tdone                   ;done if so
  458.  
  459.         seg     cs
  460.         dec     timer                   ;decrement timer
  461.         jnz     tdone
  462.         call    video_off               ;turn off screen
  463.         seg     cs
  464.         and     flags, NOT FORCE        ;clear forced flag
  465.  
  466. tdone   seg     cs
  467.         jmp     int_1C                  ;branch to old timer handler
  468.         ENDP
  469.  
  470. ;========================================
  471. ; Interrupt 21H handler.
  472.  
  473. dos_han PROC   NEAR
  474.         cmp     ah, 2Bh         ;check set date function
  475.         jne     ddone   
  476.         cmp     cx, SIGN1       ;check if first signature matches
  477.         jne     ddone   
  478.         cmp     dx, SIGN2       ;check if second signature matches
  479.         jne     ddone
  480.  
  481. ;--- external query
  482.  
  483.         call    screen_func     ;execute screen function in BX
  484.         sub     al, al          ;clear error
  485.         mov     dx, cs          ;return segment
  486.         iret                    ;exit
  487.  
  488. ;--- branch to old DOS
  489.  
  490. ddone   seg     cs
  491.         jmp     int_21          ;branch to dos handler
  492.         ENDP
  493.  
  494. ;========================================
  495. ; End of resident code/data.
  496.  
  497. end_res LABEL  NEAR             ;label marking end
  498.  
  499. ;****************************************
  500. ; Transient Data
  501.  
  502. ENVIRO  EQU    002CH            ;offset of environtment in PSP
  503. COMLINE EQU    0081H            ;start of command line characters
  504.  
  505. ;--- option table
  506.  
  507. OPT_HELP        EQU     0       ;request help
  508. OPT_INSTALL     EQU     1       ;install
  509. OPT_UNINSTALL   EQU     2       ;uninstall
  510. OPT_RESET       EQU     3       ;reset timer
  511. OPT_SHOW        EQU     4       ;force visible
  512. OPT_HIDE        EQU     5       ;force hidden
  513. OPT_TICKS       EQU     6       ;set ticks
  514. OPT_TIMEOUT     EQU     7       ;force timeout
  515.  
  516. opttab  LABEL   WORD                    ;option routine table
  517.         DW      OFFSET help
  518.         DW      OFFSET install
  519.         DW      OFFSET remove
  520.         DW      OFFSET send_reset
  521.         DW      OFFSET send_show
  522.         DW      OFFSET send_hide
  523.         DW      OFFSET send_ticks
  524.         DW      OFFSET send_timeout
  525.  
  526. ;--- messages
  527.  
  528. banner  DB      13,10,'SLEEPER  EGA Version '
  529.         DB      VER_HI+'0', '.', (VER_LO/10)+'0', (VER_LO\10)+'0'
  530.         DB      'A  Eric Tauck  10/26/1989',13,10,'$'
  531.  
  532. mes1a   DB      'Sleeper installed with timer = ','$'
  533. mes1b   DB      ' ticks',13,10,'$'
  534. mes2    DB      'Error in options, run "SLEEPER ?" for help',13,10,'$'
  535. mes3    DB      'Cannot uninstall Sleeper',13,10,'$'
  536. mes4    DB      'Sleeper removed from memory',13,10,'$'
  537. mes5    DB      'Sleeper must be installed first',13,10,'$'
  538. mes6    DB      'Sleeper already installed',13,10,'$'
  539. mes7a   DB      'Sleeper reset with timer = ','$'
  540. mes7b   DB      ' ticks',13,10,'$'
  541. mes8    DB      'Sleeper timer reset',13,10,'$'
  542. mes9    DB      'Screen forced visible',13,10,'$'
  543. mes10   DB      'Screen forced hidden',13,10,'$'
  544. mes11   DB      'Forced timeout',13,10,'$'
  545.  
  546. ;--- help message
  547.  
  548. hmes    LABEL   BYTE
  549.   DB 13,10
  550.   DB 'Installation Options:',13,10
  551.   DB 13,10
  552.   DB '  SLEEPER       install with a default timer value of 5 minutes',13,10
  553.   DB '  SLEEPER nnn   install with a timer value of 1 to 3600 seconds',13,10
  554.   DB 13,10
  555.   DB 'Resident Options:',13,10
  556.   DB 13,10
  557.   DB '  SLEEPER v     force visible screen (also when not resident)',13,10
  558.   DB '  SLEEPER h     force hidden screen (also when not resident)',13,10
  559.   DB '  SLEEPER t     force timeout',13,10
  560.   DB '  SLEEPER r     reset timer',13,10
  561.   DB '  SLEEPER nnn   reset timer with a value of 1 to 3600 seconds',13,10
  562.   DB '  SLEEPER u     uninstall',13,10
  563.   DB 13,10
  564.   DB 'Keyboard Commands:',13,10
  565.   DB 13,10
  566.   DB '  ALT-CTL-V     force visible screen',13,10
  567.   DB '  ALT-CTL-H     force hidden screen',13,10
  568.   DB '  ALT-CTL-T     force timeout',13,10
  569.   DB '  ALT-CTL-R     reset timer ',13,10
  570.   DB '$'
  571.  
  572. ;****************************************
  573. ; Transient Code
  574.  
  575. ;========================================
  576. ; Macro to display a $ terminated string
  577.  
  578. display MACRO   str
  579.         mov     ah, 9           ;display function
  580.         mov     dx, OFFSET str  ;load address
  581.         int     21H             ;execute
  582.         ENDM
  583.  
  584. ;========================================
  585. ; Display the number in AX.
  586.  
  587. number  PROC    NEAR
  588.         mov     bx, 10          ;base
  589.         sub     cx, cx          ;digit count
  590.  
  591. ;--- determine decimal digits
  592.  
  593. numeval sub     dx, dx          ;zero for divide
  594.         div     ax, bx          ;divide by base
  595.         push    dx              ;save digit on stack
  596.         inc     cx              ;increment digit count
  597.         or      ax, ax          ;check if anything left
  598.         jnz     numeval         ;loop back if so
  599.  
  600. ;--- display number
  601.  
  602. numdisp pop     dx              ;restore value
  603.         add     dl, '0'         ;convert to ASCII
  604.         mov     ah, 2           ;display function
  605.         int     21H             ;execute
  606.         loop    numdisp         ;loop for each digit
  607.  
  608.         ret
  609.         ENDP
  610.  
  611. ;========================================
  612. ; Call resident sleeper.
  613. ;
  614. ; In: BX= resident command.
  615. ;
  616. ; Out: DX= resident data segment; CY=
  617. ;      set if error (not resident).
  618.  
  619. resident PROC   NEAR
  620.         mov     ah, 2Bh         ;set date function
  621.         mov     cx, SIGN1       ;signature one
  622.         mov     dx, SIGN2       ;signature two
  623.         int     21H             ;execute
  624.         sub     al, 1           ;subtract (use SUB to set CY flag)
  625.         cmc                     ;set carry on error
  626.         ret
  627.         ENDP
  628.  
  629. ;========================================
  630. ; Process command line.
  631. ;
  632. ; Out: BX= option number; CY= set if
  633. ;      error.
  634.  
  635. options PROC    NEAR
  636.         cld
  637.  
  638. ;--- skip delimiters
  639.  
  640.         mov     si, COMLINE     ;start of command line
  641.         mov     bx, OPT_INSTALL
  642.  
  643. skdel   lodsb                   ;load character
  644.         cmp     al, 13          ;check if end of line
  645.         je      optok           ;exit if so
  646.         cmp     al, ' '         ;check if delimiter
  647.         jbe     skdel           ;loop back if so
  648.  
  649. ;--- check for standard options
  650.  
  651.         mov     dl, al          ;save character
  652.         or      al, 20H         ;convert to lower-case
  653.         mov     bx, OPT_RESET
  654.         cmp     al, 'r' 
  655.         je      optok
  656.         mov     bx, OPT_SHOW
  657.         cmp     al, 'v'
  658.         je      optok
  659.         mov     bx, OPT_HIDE
  660.         cmp     al, 'h'
  661.         je      optok
  662.         mov     bx, OPT_UNINSTALL
  663.         cmp     al, 'u'
  664.         je      optok
  665.         mov     bx, OPT_HELP
  666.         cmp     al, '?'
  667.         je      optok
  668.         mov     bx, OPT_TIMEOUT
  669.         cmp     al, 't'
  670.         je      optok
  671.  
  672. ;--- convert number
  673.  
  674.         mov     bx, 10          ;base
  675.         sub     cx, cx          ;zero total
  676.         mov     al, dl          ;restore character
  677.  
  678. evall   sub     al, '0'         ;convert to value
  679.         cmp     al, 9           ;check if out of range
  680.         ja      opterr          ;jump if so
  681.  
  682.         sub     ah, ah
  683.         xchg    ax, cx          ;total in AX, digit value in CX
  684.         mul     ax, bx          ;total times base
  685.         add     cx, ax          ;new total
  686.  
  687.         lodsb                   ;load next character
  688.         cmp     al, ' '         ;check if delimiter
  689.         ja      evall           ;loop back if not
  690.  
  691.         mov     ax, 18          ;18/ticks per second
  692.         mul     cx              ;convert
  693.         or      dx, dx          ;check if too big
  694.         jnz     opterr          ;jump if so
  695.         push    ax
  696.         mov     ax, 5           ;plus .2/ticks per sec
  697.         xchg    ax, cx
  698.         div     ax, cx          ;for every 5, add one more
  699.         pop     dx
  700.         add     dx, ax          ;total ticks
  701.         jc      opterr          ;jump if too many
  702.         mov     ticks, dx       ;save ticks
  703.         mov     bx, OPT_TICKS   ;return function
  704.  
  705. ;--- done
  706.  
  707. optok   clc
  708.         ret
  709.  
  710. ;--- error
  711.  
  712. opterr  display mes2    ;show error message
  713.         stc
  714.         ret
  715.         ENDP
  716.  
  717. ;========================================
  718. ; Display help screen.
  719. ;
  720. ; Out: AL= termination code.
  721.  
  722. help    PROC    NEAR
  723.         display hmes    ;display help text
  724.         sub     al, al  ;no error
  725.         ret
  726.         ENDP
  727.  
  728. ;========================================
  729. ; Install in memory.
  730. ;
  731. ; Out: AL= termination code (only if
  732. ;      failure).
  733.  
  734. install PROC    NEAR
  735.  
  736. ;--- check if already installed
  737.  
  738.         mov     bx, NOTHING     ;no resident operation
  739.         call    resident        ;link to resident version
  740.         jc      noierr          ;jump if okay
  741.         display mes6            ;display error message
  742.         mov     al, -1          ;return error code
  743.         ret
  744.  
  745. ;--- start installation
  746.  
  747. noierr  call    reset_timer     ;reset timer
  748.  
  749. ;--- display message
  750.  
  751.         display mes1a           ;first part
  752.         mov     ax, ticks       ;load timer value
  753.         call    number          ;display
  754.         display mes1b           ;second part
  755.  
  756. ;--- save keyboard interrupt 9
  757.  
  758.         mov     ax, 3509H               ;get keyboard interrupt
  759.         int     21H                     ;execute
  760.         mov     WORD int_09, bx         ;save offset
  761.         mov     WORD int_09+2, es       ;save segment
  762.  
  763. ;--- install keyboard interrupt 9
  764.  
  765.         mov     ax, 2509H               ;set keyboard interrupt
  766.         mov     dx, OFFSET key_han      ;keyboard handler
  767.         int     21H                     ;execute
  768.  
  769. ;--- save video interrupt 10
  770.  
  771.         mov     ax, 3510H               ;get video interrupt
  772.         int     21H                     ;execute
  773.         mov     WORD int_10, bx         ;save offset
  774.         mov     WORD int_10+2, es       ;save segment
  775.  
  776. ;--- install video interrupt 10
  777.  
  778.         mov     ax, 2510H               ;set video interrupt
  779.         mov     dx, OFFSET vid_han      ;video handler
  780.         int     21H                     ;execute
  781.  
  782. ;--- save timer interrupt 1C
  783.  
  784.         mov     ax, 351CH               ;get keyboard interrupt
  785.         int     21H                     ;execute
  786.         mov     WORD int_1C, bx         ;save offset
  787.         mov     WORD int_1C+2, es       ;save segment
  788.  
  789. ;--- install timer interrupt 1C
  790.  
  791.         mov     ax, 251CH               ;set interrupt 1C
  792.         mov     dx, OFFSET tic_han      ;timer tick handler
  793.         int     21H                     ;execute
  794.         call    reset_timer             ;reset timer
  795.  
  796. ;--- save keyboard fetch interrupt 16
  797.  
  798.         mov     ax, 3516H               ;get keyboard interrupt
  799.         int     21H                     ;execute
  800.         mov     WORD int_16, bx         ;save offset
  801.         mov     WORD int_16+2, es       ;save segment
  802.  
  803. ;--- install keyboard fetch interrupt 16
  804.  
  805.         mov     ax, 2516H               ;set interrupt 16
  806.         mov     dx, OFFSET key2_han     ;keyboard fetch handler
  807.         int     21H                     ;execute
  808.  
  809. ;--- save DOS interrupt 21
  810.  
  811.         mov     ax, 3521H               ;get keyboard interrupt
  812.         int     21H                     ;execute
  813.         mov     WORD int_21, bx         ;save offset
  814.         mov     WORD int_21+2, es       ;save segment
  815.  
  816. ;--- install DOS interrupt 21
  817.  
  818.         mov     ax, 2521H               ;set interrupt 21
  819.         mov     dx, OFFSET dos_han      ;DOS handler
  820.         int     21H                     ;execute
  821.  
  822. ;--- install
  823.  
  824.         mov     dx, OFFSET end_res      ;end of resident code
  825.         mov     cl, 4
  826.         shr     dx, cl                  ;convert to paragraph
  827.         inc     dx                      ;round up, paragraphs to reserve
  828.  
  829.         mov     ax, 3100H       ;resident-terminate with exit code 0
  830.         int     21H             ;execute
  831.         ENDP
  832.  
  833. ;========================================
  834. ; Remove from memory.
  835. ;
  836. ; Out: AL= termination code.
  837.  
  838. remove  PROC    NEAR
  839.  
  840. ;--- check if installed
  841.  
  842.         mov     bx, NOTHING     ;no resident operation
  843.         call    resident        ;link to resident version
  844.         jnc     norerr          ;jump if okay
  845.         display mes5            ;display error message
  846.         mov     al, -1          ;return error code
  847.         ret
  848.  
  849. ;--- start removal
  850.  
  851. norerr  push    ds
  852.         mov     ds, dx          ;switch to resident data segment
  853.  
  854. ;=== verify vectors
  855.  
  856.         mov     cx, ds
  857.  
  858. ;--- verify interrupt 9
  859.  
  860.         mov     ax, 3509H               ;get interrupt
  861.         int     21H                     ;execute
  862.         cmp     bx, OFFSET key_han      ;check offset
  863.         jne     verr
  864.         mov     ax, es
  865.         cmp     ax, cx                  ;check segment
  866.         jne     verr
  867.  
  868. ;--- verify interrupt 10
  869.  
  870.         mov     ax, 3510H               ;get interrupt
  871.         int     21H                     ;execute
  872.         cmp     bx, OFFSET vid_han      ;check offset
  873.         jne     verr
  874.         mov     ax, es
  875.         cmp     ax, cx                  ;check segment
  876.         jne     verr
  877.  
  878. ;--- verify interrupt 1C
  879.  
  880.         mov     ax, 351CH               ;get interrupt
  881.         int     21H                     ;execute
  882.         cmp     bx, OFFSET tic_han      ;check offset
  883.         jne     verr
  884.         mov     ax, es
  885.         cmp     ax, cx                  ;check segment
  886.         jne     verr
  887.  
  888. ;--- verify interrupt 16
  889.  
  890.         mov     ax, 3516H               ;get interrupt
  891.         int     21H                     ;execute
  892.         cmp     bx, OFFSET key2_han     ;check offset
  893.         jne     verr
  894.         mov     ax, es
  895.         cmp     ax, cx                  ;check segment
  896.         jne     verr
  897.  
  898. ;--- verify interrupt 21
  899.  
  900.         mov     ax, 3521H               ;get interrupt
  901.         int     21H                     ;execute
  902.         cmp     bx, OFFSET dos_han      ;check offset
  903.         jne     verr
  904.         mov     ax, es
  905.         cmp     ax, cx                  ;check segment
  906.         jne     verr
  907.         jmps    unhook
  908.  
  909. ;--- error
  910.  
  911. verr    pop     ds
  912.         display mes3            ;display message
  913.         mov     al, -1          ;error code
  914.         ret
  915.  
  916. ;=== unhook interrupts
  917.  
  918. unhook  push    ds              ;save resident segment
  919.         push    ds
  920.         pop     es              ;transfer resident segment to ES
  921.  
  922. ;--- unhook 9
  923.  
  924.         mov     ax, 2509H               ;set interrupt function
  925.         seg     es
  926.         mov     dx, WORD int_09         ;offset
  927.         seg     es
  928.         mov     ds, WORD int_09+2       ;segment
  929.         int     21H                     ;execute
  930.  
  931. ;--- unhook 10
  932.  
  933.         mov     ax, 2510H               ;set interrupt function
  934.         seg     es
  935.         mov     dx, WORD int_10         ;offset
  936.         seg     es
  937.         mov     ds, WORD int_10+2       ;segment
  938.         int     21H                     ;execute
  939.  
  940. ;--- unhook 16
  941.  
  942.         mov     ax, 2516H               ;set interrupt function
  943.         seg     es
  944.         mov     dx, WORD int_16         ;offset
  945.         seg     es
  946.         mov     ds, WORD int_16+2       ;segment
  947.         int     21H                     ;execute
  948.  
  949. ;--- unhook 1C
  950.  
  951.         mov     ax, 251CH               ;set interrupt function
  952.         seg     es
  953.         mov     dx, WORD int_1C         ;offset
  954.         seg     es
  955.         mov     ds, WORD int_1C+2       ;segment
  956.         int     21H                     ;execute
  957.  
  958. ;--- unhook 21
  959.  
  960.         mov     ax, 2521H               ;set interrupt function
  961.         seg     es
  962.         mov     dx, WORD int_21         ;offset
  963.         seg     es
  964.         mov     ds, WORD int_21+2       ;segment
  965.         int     21H                     ;execute
  966.  
  967.         pop     ds              ;restore resident segment
  968.  
  969. ;=== release memory
  970.  
  971. ;--- release environment
  972.  
  973.         mov     ax, [ENVIRO]    ;load environment segment
  974.         or      ax, ax          ;check if any
  975.         jz      noenv
  976.         mov     es, ax
  977.         mov     ah, 49H         ;release memory function
  978.         int     21H             ;execute
  979.  
  980. ;--- release code
  981.  
  982. noenv   push    ds
  983.         pop     es
  984.         mov     ah, 49H         ;release memory function
  985.         int     21H             ;execute
  986.  
  987.         pop     ds              ;restore local DS
  988.  
  989.         display mes4            ;display message
  990.         sub     al, al          ;no error
  991.         ret
  992.         ENDP
  993.  
  994. ;========================================
  995. ; Reset resident sleeper.
  996.  
  997. send_reset PROC NEAR
  998.         mov     bx, RESET       ;command
  999.         call    resident        ;send to resident sleeper
  1000.         jc      sreserr
  1001.  
  1002. ;--- success
  1003.  
  1004.         display mes8            ;message
  1005.         mov     al, 0           ;no error
  1006.         ret
  1007.  
  1008. ;--- error
  1009.  
  1010. sreserr display mes5            ;error message
  1011.         mov     al, -1          ;error code
  1012.         ret
  1013.         ENDP
  1014.  
  1015. ;========================================
  1016. ; Force a timeout.
  1017.  
  1018. send_timeout PROC NEAR
  1019.         mov     bx, TIME        ;command
  1020.         call    resident        ;send to resident sleeper
  1021.         jc      stimerr
  1022.  
  1023. ;--- success
  1024.  
  1025.         display mes11           ;message
  1026.         mov     al, 0           ;no error
  1027.         ret
  1028.  
  1029. ;--- error
  1030.  
  1031. stimerr display mes5            ;error message
  1032.         mov     al, -1          ;error code
  1033.         ret
  1034.         ENDP
  1035.  
  1036. ;========================================
  1037. ; Show screen.
  1038.  
  1039. send_show PROC NEAR
  1040.         mov     bx, SHOW        ;command
  1041.         call    resident        ;send to resident sleeper
  1042.         jnc     sshook
  1043.  
  1044. ;--- turn on screen
  1045.  
  1046.         call    video_on        ;turn on video
  1047.  
  1048. ;--- done
  1049.  
  1050. sshook  display mes9            ;message
  1051.         mov     al, 0           ;no error
  1052.         ret
  1053.         ENDP
  1054.  
  1055. ;========================================
  1056. ; Hide screen.
  1057.  
  1058. send_hide PROC NEAR
  1059.         mov     bx, HIDE        ;command
  1060.         call    resident        ;send to resident sleeper
  1061.         jnc     shidok
  1062.  
  1063. ;--- turn off screen
  1064.  
  1065.         call    video_off       ;turn off video
  1066.  
  1067. ;--- done
  1068.  
  1069. shidok  display mes10           ;message
  1070.         mov     al, 0           ;no error
  1071.         ret
  1072.         ENDP
  1073.  
  1074. ;========================================
  1075. ; Set number of ticks in resident
  1076. ; sleeper.
  1077.  
  1078. send_ticks PROC NEAR
  1079.  
  1080. ;--- check if installed
  1081.  
  1082.         mov     bx, NOTHING     ;no resident operation
  1083.         call    resident        ;link to resident version
  1084.         jc      ticerr          ;jump if not installed
  1085.  
  1086. ;--- modify resident sleeper
  1087.  
  1088.         mov     ax, ticks       ;load local tick count
  1089.         push    ds
  1090.         mov     ds, dx          ;switch to resident segment
  1091.         mov     ticks, ax       ;set new tick count
  1092.         pop     ds
  1093.         mov     bx, RESET       ;command
  1094.         call    resident        ;send to resident sleeper
  1095.  
  1096. ;--- display message
  1097.  
  1098.         display mes7a           ;first part
  1099.         mov     ax, ticks       ;load timer value
  1100.         call    number          ;display
  1101.         display mes7b           ;second part
  1102.  
  1103.         mov     al, 0           ;no error
  1104.         ret
  1105.  
  1106. ;--- goto install
  1107.  
  1108. ticerr  jmp     install         ;goto install
  1109.         ENDP
  1110.  
  1111. ;****************************************
  1112. ; Program entry point.
  1113.  
  1114. start   display banner                  ;display banner
  1115.         call    options                 ;parse command line
  1116.         mov     al, -1                  ;error code if parameter error
  1117.         jc      term                    ;jump if error
  1118.         shl     bx                      ;adjust option number to offset
  1119.         call    WORD [opttab + bx]      ;call option routine
  1120.  
  1121. ;--- terminate, result code in AL
  1122.  
  1123. term    mov     ah, 4CH         ;exit function
  1124.         int     21H             ;execute
  1125.